package org.cos.generation.epda;

import java.util.LinkedList;
import java.util.List;

import org.cos.generation.epda.action.Action;

/**
 * @author Jinglei Ren
 *
 */
public class State {
	
	/** The unique identifier for a state. */
	private int identifier;
	
	/** Mark whether the state is a return state. */
	private boolean returnFlag = false;

	/** Store the all transitions form the state. */
	private List<Transition> transitions;
	
	/**
	 * Constructor.
	 * @param id
	 */
	public State(int id) {
		identifier = id;
		transitions = new LinkedList<Transition>();
	}
	
	public List<Transition> getTransitions() {
		return transitions;
	}
	
	public void setReturn() {
		returnFlag = true;
	}
	
	public boolean isReturn() {
		return returnFlag;
	}
	
	public Integer getId() {
		return identifier;
	}
	
	public void addTransition(int tailIndex, Method method, 
			List<Condition> conditions, List<Action> actions) {
		transitions.add(new Transition(tailIndex, method, 
				conditions, actions));
	}
	
	public String toString() {
		return getId().toString();
	}
	
	public boolean equals(Object o) {
		if (o instanceof State) {
			State oState = (State) o;
			if (identifier == oState.identifier && 
					returnFlag == oState.returnFlag &&
							transitions.equals(oState.transitions)) {
				return true;
			}
			return false;
		}
		return false;
	}
	
	public class Transition {
		
		private int tailIndex;
		
		private Method method;
		
		private List<Condition> conditions =
			new LinkedList<Condition>();
		
		private List<Action> actions =
			new LinkedList<Action>();
		
		public Transition(int tailIndex, Method method, 
				List<Condition> conditions, List<Action> actions) {
			this.tailIndex = tailIndex;
			this.method = method;
			if (conditions != null) {
				this.conditions.addAll(conditions);
			}
			if (actions != null) {
				this.actions.addAll(actions);
			}
		}
		
		public Transition(int tailIndex, Method method, 
				Condition condition, Action action) {
			this.tailIndex = tailIndex;
			this.method = method;
			if (conditions != null) {
				this.conditions.add(condition);
			}
			if (actions != null) {
				this.actions.add(action);
			}
		}
		
		public Method getMethod() {
			return method;
		}
		
		public Integer getTailIndex() {
			return tailIndex;
		}
		
		public void setTailIndex(int tailIndex) {
			this.tailIndex = tailIndex;
		}
		
		public void setNull() {
			method = null;
			conditions = null;
			actions = null;
		}
		
		public List<Condition> getConditions() {
			return conditions;
		}
		
		public List<Action> getActions() {
			return actions;
		}
		
		public boolean equals(Object o) {
			if (o instanceof Transition) {
				Transition oTrans = (Transition) o;
				if (tailIndex == oTrans.tailIndex &&
						((method == null && oTrans.method == null) || method.equals(oTrans.method)) &&
						conditions.equals(oTrans.conditions) &&
						actions.equals(oTrans.actions)) {
					return true;
				}
				return false;
			}
			return false;
		}
			
	}
	
}
